/*

Copyright (C) 2000 - 2008 Christian Kreibich <christian@whoop.org>.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies of the Software and its documentation and acknowledgment shall be
given in the documentation and software packages that this Software was
used.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

*/
#ifndef __nd_gui_h
#define __nd_gui_h

#include <gtk/gtk.h>
#include <nd_packet.h>
#include <nd_trace.h>

/**
 * ND_MenuEntryCB - callback signature used for protocol menu entries.
 * @packet: currently edited packet.
 * @header: pointer to header structure of currently edited protocol.
 * @value: the value for the affected header field that is set by the menu item.
 *
 * Functions of this signature are used for nd_gui_create_menu().
 * Each menu item supplies a specific header field value, which gets
 * passed to the callback as @value. @header is automatically set
 * correctly and points to the beginning of the protocol data currently
 * edited when the menu was popped up (including the correct nesting
 * level).
 */
typedef void (*ND_MenuEntryCB) (LND_Packet  *packet,
				guchar      *header,
				int          value);

struct nd_gtk_menu
{
	guint			  menu_merge_id;
	GtkAction		 *menu_action;
	guint			 *item_merge_ids;
	unsigned		  item_merge_id_count;
	GtkAction		**item_actions;
	unsigned		  item_action_count;
	GtkActionGroup	 *action_group;
};

struct nd_menu_data
{
  const char                   *label;
  const char                   *tooltip;
  int                           value;
  ND_MenuEntryCB                callback;
};


typedef enum {
  ND_COLOR_BG,
  ND_COLOR_RED,
  ND_COLOR_YELLOW
} ND_GuiColor;


/* global list of gtk objects */
extern GtkBuilder		 *nd_builder;
extern GtkWindow		 *nd_toplevel_window;
extern GtkUIManager		 *nd_ui_manager;


/**
 * nd_gui_init - initializes GUI stuff.
 * @argc: argc from main()
 * @argv: argv from main()
 *
 * This function initializes GTK, sets up the GTKBuilder interface,
 * and gets pointers to all the GUI objects we'll want to manage
 * during runtime.
 */
unsigned int nd_gui_init(int argc, char* argv[]);


/**
 * nd_gui_shutdown - cleans up GUI stuff
 *
 * This function performs any clean up required for the GUI, such
 * as freeing memory.
 */
void nd_gui_shutdown();


/**
 * nd_gtk_builder_get_object - finds a GTK object in a list of object
 * @objs: a pointer-pointer to a list of the objects
 * @key: the name of the object to find
 * @return: the object named key or NULL if the object does
 *            not exist in the list
 */
GObject *nd_gtk_builder_get_object(GSList **objs, char *key);


/**
 * nd_gui_init_setup - post-init setup of the GUI
 *
 * The function initializes Netdude GUI components beyond what
 * can be done through GTKBuilder, e.g. the progress bar, etc.
 */
void         nd_gui_init_setup(void);


/**
 * nd_gui_sync_menus - reflect app status in GUI menus.
 *
 * This function sets various GUI elements sensitive or insensitive
 * according to the current packet/trace selection.
 */
void         nd_gui_sync_menus(void);


/**
 * nd_gui_sync_edit_menu - reflect app status in edit menu.
 */
void         nd_gui_sync_edit_menu(void);

/**
 * nd_gui_sync_file_menu - reflect app status in file menu.
 */
void         nd_gui_sync_file_menu(void);

/**
 * nd_gui_sync_go_menu - reflect app status in go menu.
 */
void         nd_gui_sync_go_menu(void);

/**
 * nd_gui_sync_protocol_menu - reflect app status in protocol menu.
 */
void         nd_gui_sync_protocol_menu(void);



/**
 * nd_gui_show_packet_menu - pops up packet menu.
 * @event: mouse event that contains coordinates where to pop up menu.
 *
 * This function pops up the packet menu when the user
 * right-clicks a line in the packet list.
 */
void         nd_gui_show_packet_menu(GdkEventButton *event);


/**
 * nd_gui_show_iterator_mode_menu - pops up per-trace iterator mode menu.
 * @event: mouse event that contains coordinates where to pop up menu.
 *
 * This function pops up the packet iteration mode menu when the user
 * clicks on the button in the trace's tab.
 */
void         nd_gui_show_iterator_mode_menu(GdkEventButton *event);





/**
 * nd_gui_num_packets_set - updates the number of packets field in the main window.
 *
 * The function updates the field in the lower left containing
 * the number of packets of the current trace.
 */
void         nd_gui_num_packets_set(void);


/**
 * nd_gui_set_trace_status - updates GUI to trace's modification status.
 * @trace: trace to sync GUI to.
 *
 * The function adjusts the GUI to reflect the modification status
 * of @trace (at the moment this means that the close button of
 * @trace is displayed either red or green).
 */
void         nd_gui_set_trace_status(LND_Trace *trace);


/**
 * nd_gui_iteration_mode_set - updates GUI to trace's iterator mode.
 * @trace: trace to sync GUI to.
 *
 * The function adjusts the GUI to reflect the selected iterator
 * mode of @trace.
 */
void         nd_gui_iterator_mode_set(LND_Trace *trace);


/**
 * nd_gui_statusbar_set - sets the status bar content.
 * @text: new statusbar message.
 *
 * The function sets the statusbar content to @text, and schedules
 * a timout that clears the statusbar after a little while.
 */
void         nd_gui_statusbar_set(const char *text);


/**
 * nd_gui_statusbar_set_noclear - sets the status bar content.
 * @text: new statusbar message.
 *
 * The function sets the statusbar content to @text just like
 * nd_gui_statusbar_set(), but doesn't schedule a timeout to
 * clear the bar.
 */
void         nd_gui_statusbar_set_noclear(const char *text);


/**
 * nd_gui_statusbar_clear - clears status bar message.
 * @data: unused.
 *
 * The function immediately clears the status bar and is used 
 * by nd_gui_statusbar_set(). @data is not used,
 * nor is the return value, these only exist to make
 * this function usable as a GTK timeout callback.
 *
 * Returns: ignored.
 */
gint         nd_gui_statusbar_clear(gpointer data);


/**
 * nd_gui_pbar_reset - initializes/resets the progress bar to a given value.
 * @num_total: number of steps between 0% and 100%.
 *
 * The function initializes the progress bar in the lower right
 * part of the main window to @num_steps number of steps.
 */
void         nd_gui_pbar_reset(int num_total);

/**
 * nd_gui_pbar_inc - increments progress bar.
 * @num_inc: value to add to progress bar.
 *
 * The function increments the progress bar by @num_inc units. The value
 * is bounded by the maximum value specified when nd_gui_pbar_reset()
 * was called, so you cannot pass something "too large" here.
 */
void         nd_gui_pbar_inc(int num_inc);

/**
 * nd_gui_pbar_clear - resets progress bar.
 * @interval: delay in milliseconds before the progress bar is cleared.
 *
 * The function clears the progress bar in the main window, after
 * waiting the given amount of time if specified.
 */
void         nd_gui_pbar_clear(int interval);

/**
 * nd_gui_pbar_start_activity - starts activity display in the progress bar.
 * 
 * The function starts activity display in the main window, causing
 * a small bar to slide back and forth in the progress bar.
 */
void         nd_gui_pbar_start_activity(void);

/**
 * nd_gui_pbar_stop_activity - stops activity display in the progress bar.
 *
 * The function stops activity display in the progress bar.
 */
void         nd_gui_pbar_stop_activity(void);


void         nd_gui_list_freeze(LND_Trace *trace);
void         nd_gui_list_thaw(LND_Trace *trace);

/**
 * nd_gui_list_incomplete_column_visible - enables/disables display of the completeness column.
 * @trace: trace whose list widget to adjust.
 * @visible: whether to show or hide the column.
 *
 * The packet lists for each trace can provide an additional column indicating
 * whether a packet was captured completely or not. This function specifies
 * whether this column is visible or not. @clist is usually obtained from
 * the current trace as trace->list.
 */
void         nd_gui_list_set_incomplete_column_visible(LND_Trace *trace, gboolean visible);

/**
 * nd_gui_list_set_row_incomplete - toggles a given line's completeness display.
 * @trace: trace whose list widget to adjust.
 * @row: which row to update.
 * @incomplete: whether to mark the row as an incomplete packet or not.
 *
 * The function adjusts the completeness status in the GUI for the given
 * packet. See also nd_gui_list_incomplete_column_visible(). The function
 * does not adjust any internal structures -- only the GUI.
 */
void         nd_gui_list_set_row_incomplete(LND_Trace *trace, int row, gboolean incomplete);

/**
 * nd_gui_list_set_row_filtered - toggles a given line's filter status.
 * @trace: trace whose list widget to update.
 * @row: which row to update.
 * @filtered: whether to mark the row as filtered or not.
 *
 */
void         nd_gui_list_set_row_filtered(LND_Trace *trace, int row, gboolean filtered);

/**
 * nd_gui_list_remove_selected_rows - removes selected rows from list widget.
 * @trace: trace whose list widget to update.
 *
 * The function removes the selected rows from @clist. This updates
 * only the widget, no signals are emitted. Use the clist functions
 * for full service.
 */
void         nd_gui_list_remove_selected_rows(LND_Trace *trace);


/**
 * nd_gui_list_remove_row - removes a single row from list widget.
 * @trace: trace whose list widget to update.
 * @index: row number to remove.
 *
 * The function removes the specified row from @trace's list widget,
 * (counting starts at zero). This updates only the widget, no
 * signals are emitted. Use the clist functions for full service.
 */
void         nd_gui_list_remove_row(LND_Trace *trace, guint index);


/**
 * nd_gui_list_insert_row - inserts a single row into the list widget.
 * @packet: packet whose data to insert.
 * @index: row number of the new line.
 *
 * The function inserts the packet's tcpdump data as a new row
 * into the packet trace's list widget.
 */
void         nd_gui_list_insert_row(LND_Packet *packet, int index);


/**
 * nd_gui_list_clear - removes all rows from list widget.
 * @trace: trace whose list widget to update.
 *
 * The function removes all entries from @trace's list widget,
 * without emitting any signals.
 */
void         nd_gui_list_clear(LND_Trace *trace);


/**
 * nd_gui_list_update - updates all tcpdump lines.
 * @trace: trace to update.
 *
 * The function refreshes the tcpdump output for @trace.
 */
void         nd_gui_list_update(LND_Trace *trace);


/**
 * nd_gui_list_update_packet - updates tcpdump output for packet.
 * @packet: packet whose tcpdump output to update.
 *
 * The function updates the tcpdump output of @packet. The packet
 * is sent anew to the tcpdump process, then the text is updated.
 * Context is always looked up. The completeness column is updated as well.
 */
void         nd_gui_list_update_packet(const LND_Packet *packet);


/**
 * nd_gui_list_update_packet_at_index - faster version of nd_gui_list_update_packet().
 * @packet: packet whose tcpdump output to update.
 * @index: index of @packet in trace.
 *
 * If you know the index of @packet in its trace, use this function
 * instead of nd_gui_list_update_packet().
 */
void         nd_gui_list_update_packet_at_index(const LND_Packet *packet, int index);


/**
 * nd_gui_list_select_packet - selects a given row in the list widget.
 * @trace: trace to update.
 * @index: row number to select.
 *
 * The function selects row @index in @trace's list widget. A signal
 * is emitted.
 */
void         nd_gui_list_select_packet(LND_Trace *trace, guint index);


/**
 * nd_gui_list_unselect_packet - unselects a given row in the list widget.
 * @trace: trace to update.
 * @index: row number to unselect.
 *
 * The function unselects row @index in @trace's list widget. A signal
 * is emitted.
 */
void         nd_gui_list_unselect_packet(LND_Trace *trace, guint index);


/**
 * nd_gui_list_unselect_all - unselects all packets in list widget.
 * @trace: trace to update.
 * @emit_signal: whether to emit unselect signals or not.
 *
 * The function unselects all rows in @trace's list widget. A signal
 * is emitted depending on @emit_signal.
 */
void         nd_gui_list_unselect_all(LND_Trace *trace, gboolean emit_signal);


/**
 * nd_gui_list_select_all - selects all packets in list widget.
 * @trace: trace to update.
 * @emit_signal: whether to emit select signals or not.
 *
 * The function elects all rows in @trace's list widget. A signal
 * is emitted depending on @block_signal.
 */
void         nd_gui_list_select_all(LND_Trace *trace, gboolean emit_signal);


/**
 * nd_gui_list_update_packet_state - updates tcpdump output line directly.
 * @packet: packet whose tcpdump output to update.
 *
 * The function takes the tcpdump output from the list widget and
 * iterates over all protocol in the packet, calling their
 * update_tcpdump_line() implementations.
 */
void         nd_gui_list_update_packet_state(const LND_Packet *packet);

/**
 * nd_gui_list_update_packet_state_at_index - faster version of nd_gui_list_update_packet_state()
 * @packet: packet whose tcpdump output to update.
 * @index: index of @packet in its trace.
 *
 * If you know the index of @packet in its trace, use this function
 * instead of nd_gui_list_update_packet_state().
 */
void         nd_gui_list_update_packet_state_at_index(const LND_Packet *packet, int index);


/**
 * nd_gui_set_windowtitle - sets main window title.
 * @filename: new (canonical) filename to display in window title.
 *
 * The function displays the given file name in the window title.
 * Depending on the current preferences, the canonical filename
 * or the filename only will be shown.
*/
void         nd_gui_set_windowtitle(const char *filename);


/**
 * nd_gui_timestamp_schedule - schedules display of timestamp.
 * @clist: list widget with relevant row.
 * @event: event containing the coordinates of the mouse.
 *
 * The function schedules timestamp tooltip to be displayed.
 * The delay depends on the user's preferences settings.
 */
void         nd_gui_timestamp_schedule(GtkCList *clist, GdkEventMotion *event);


/**
 * nd_gui_timestamp_hide - hides the timestamp tooltip.
 */
void         nd_gui_timestamp_hide(void);


/**
 * nd_gui_proto_menu_register - protocol-specific menu registrator.
 * @proto: Protocol providing a menu.
 *
 * Protocol plugins can provide a menu for any features they provide.
 * This function takes care of hooking those menus into the main window.
 */
void         nd_gui_proto_menu_register(LND_Protocol *proto);

/**
 * nd_gui_trace_add - adds a trace to the GUI.
 * @trace: trace to add to GUI.
 * 
 * The function adds @trace to the GUI. No other internal
 * data structures are touched. However, nd_trace_registry_set_current()
 * is called automatically through the callback that gets activated
 * when the trace is added.
 */
void         nd_gui_trace_add(LND_Trace *trace);

/**
 * nd_gui_trace_remove - removes a trace from the GUI.
 * @trace: trace to remove from GUI:
 *
 * The function removes @trace from the GUI. No other internal
 * data structures are touched.
 */
void         nd_gui_trace_remove(LND_Trace *trace);


/**
 * nd_gui_trace_new_tab - creates new trace tab.
 * @trace: trace for which tab is created.
 *
 * The function creates a new GTK notebook tab for @trace
 * and hooks them into the given trace.
 */
void         nd_gui_trace_new_tab(LND_Trace *trace);

/**
 * nd_gui_trace_set_name - syncs the tab label of a trace to its filename
 * @trace: trace for which tab is updated.
 * 
 * The function updates the notebook tab label of @trace
 * to its current name and whether or not the canonical
 * or the local filename is displayed.
 */
void         nd_gui_trace_set_name(LND_Trace *trace);


/**
 * nd_gui_widget_set_color - adjusts color of a widget.
 * @widget: widget to modify.
 * @color: color to use.
 *
 * The function changes the color of the given widget
 * by scaling its color values in the desired directions.
 * The actual effect will depend on the GTK theme used.
 * This function is used to implement
 * nd_proto_info_field_set_state().
 */
void         nd_gui_widget_set_color(GtkWidget *widget, ND_GuiColor color);


/**
 * nd_gui_create_menu - creates menu out of menu data.
 * @data: array of ND_MenuDatas.
 *
 * The function creates a menu out of the given ND_MenuData
 * array and returns it. The last entry in the array must have a
 * label value of NULL, which is easy since the @data array
 * is supposed to be declared statically.
 *
 * Returns: created menu.
 */
ND_GtkMenu  *nd_gui_create_menu(ND_MenuData *data);


/**
 * nd_gui_proto_table_create - creates a GUI table for a protocol header.
 * @trace: trace to which table belongs.
 * @pinf: protocol type and nesting.
 *
 * The function creates a GUI table based upon the specification of
 * a protocol. The result depends on the statically initialized array
 * which the ND_Protocol's 'fields' pointer points to. Its last array
 * entry must contain a %NULL value.
 *
 * Returns: created table, a GtkTable.
 */
GtkWidget   *nd_gui_proto_table_create(LND_Trace *trace,
				       LND_ProtoInfo *pinf);

/**
 * nd_gui_proto_table_clear - reset optional fields in protocol header table.
 * @trace: trace to which table belongs.
 * @pinf: protocol type and nesting.
 *
 * Additional buttons can be added to protocol header tables at any time
 * using nd_gui_proto_table_add(). This is the mechanism to display e.g. IP
 * options etc. To remove any previously added optional buttons,
 * call this function.
 */
void         nd_gui_proto_table_clear(LND_Trace *trace,
				      LND_ProtoInfo *pinf);

/**
 * nd_gui_proto_table_add - adds an optional field to a protocol header table.
 * @trace: trace to which table belongs.
 * @pinf: protocol type and nesting.
 * @field: specification of the field.
 * @data: arbitrary data passed in as void pointer.
 * @is_error: whether the header field is in an erroneous state or not.
 *
 * The function adds an optional button to the protocol header table
 * of a given protocol. @data is used to fill the @field label string with
 * the actual value. It depends on the format string in the @field structure,
 * what data needs to be passed here. When @is_error is %TRUE, the button
 * is changed in color accordingly.
 */
void         nd_gui_proto_table_add(LND_Trace *trace,
				    LND_ProtoInfo *pinf,
				    ND_ProtoField *field,
				    void *data,
				    gboolean is_error);


/**
 * nd_gui_proto_table_block_events - blocks event propagation.
 * @trace: trace affected.
 * @pi: protocol type and nesting.
 *
 * The function blocks all event propagation from the protocol header
 * table for the protocol instance specified in @pi. Match this up
 * with nd_gui_proto_table_unblock_events()!
 */
void         nd_gui_proto_table_block_events(LND_Trace *trace, LND_ProtoInfo *pi);

/**
 * nd_gui_proto_table_unblock_events - unblocks event propagation.
 * @trace: trace affected.
 * @pi: protocol type and nesting.
 *
 * The function unblocks all event propagation from the protocol header
 * table for the protocol instance specified in @pi. Use this after
 * blocking the events with nd_gui_proto_table_block_events().
 */
void         nd_gui_proto_table_unblock_events(LND_Trace *trace, LND_ProtoInfo *pi);


/**
 * nd_gui_add_monowidth_widget - registers a widget as needing monowidth font.
 * @widget: widget that uses a monowidth font.
 *
 * Netdude keeps track of all widgets that need a monowidth font (like
 * all the tcpdump packet lists). Use this function to add a widget
 * to that set.
 */
void         nd_gui_add_monowidth_widget(GtkWidget *widget);

/**
 * nd_gui_del_monowidth_widget - removes a widget from the set of monowidth widgets.
 * @widget: widget to forget.
 *
 * When monowidth widgets get destroyed, make sure you call this function
 * so that Netdude doesn't unnecessarily keep track of them.
 */
void         nd_gui_del_monowidth_widget(GtkWidget *widget);

/**
 * nd_gui_update_monowidth_widget - update monowidth widgets to font.
 *
 * The function updates the set of monowidth widgets to use the 
 * currently specified monowidth font. Gets called when the user
 * updated the monowidth font preference.
 */
void         nd_gui_update_monowidth_widgets(void);

void         nd_gui_update_view_indicator(void);
void         nd_gui_update_area_indicator(void);

#endif
